package com.example.demo2.service.impl;

import com.example.demo2.entity.CalHistory;
import com.example.demo2.entity.Result;
import com.example.demo2.mapper.CalHistoryMapper;
import com.example.demo2.mapper.ResultMapper;
import com.example.demo2.request.CalculationRequest;
import com.example.demo2.service.CalculationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Service
public class CalculationServiceImpl implements CalculationService {

    @Autowired
    private ResultMapper resultMapper;

    @Autowired
    private CalHistoryMapper calHistoryMapper;

    private AtomicInteger progress = new AtomicInteger(0);
    private int totalCombinations = 1;

    @Override
    public void calculateAndSaveResults(CalculationRequest request) {
        String calcName = request.getCalcName();
        List<CalculationRequest.AminoData> aminoDataList = request.getAminoData();
        float variable1 = request.getVariable1();
        float variable2 = request.getVariable2();
        float variable3 = request.getVariable3(); // 新增 variable3
        String selectedAmino = request.getSelectedAmino();

        // 插入计算历史记录
        calHistoryMapper.insertCalHistory(new CalHistory(calcName, new Date()));

        totalCombinations = 1;
        for (CalculationRequest.AminoData amino : aminoDataList) {
            totalCombinations *= (amino.getQuantity() + 1);
        }

        progress.set(0);

        // 生成所有组合并计算
        generateAndCalculateCombinations(calcName, aminoDataList, variable1, variable2, variable3, selectedAmino);
    }

    private void generateAndCalculateCombinations(String calcName, List<CalculationRequest.AminoData> aminoDataList, float variable1, float variable2, float variable3, String selectedAmino) {
        int[] maxCounts = new int[aminoDataList.size()];
        float[] values = new float[aminoDataList.size()];
        String[] names = new String[aminoDataList.size()];

        int selectedIndex = -1;

        for (int i = 0; i < aminoDataList.size(); i++) {
            maxCounts[i] = (int) aminoDataList.get(i).getQuantity();
            values[i] = aminoDataList.get(i).getValue();
            names[i] = aminoDataList.get(i).getName();
            if (names[i].equals(selectedAmino)) {
                selectedIndex = i;
            }
        }

        generateCombinations(new int[aminoDataList.size()], maxCounts, values, names, 0, calcName, variable1, variable2, variable3, selectedIndex);
    }

    private void generateCombinations(int[] current, int[] maxCounts, float[] values, String[] names, int index, String calcName, float variable1, float variable2, float variable3, int selectedIndex) {
        if (index == current.length) {
            BigDecimal total = BigDecimal.ZERO;
            StringBuilder content = new StringBuilder();

            for (int i = 0; i < current.length; i++) {
                total = total.add(BigDecimal.valueOf(values[i] * current[i]));
                content.append(names[i]).append("(").append(current[i]).append("), ");
            }

            // 公式一计算
            BigDecimal result1 = total.add(BigDecimal.valueOf(1.0073f * variable1)).divide(BigDecimal.valueOf(variable1), 2, RoundingMode.HALF_UP);
            resultMapper.insertResult(new Result(calcName, "公式一", result1.floatValue(), content.toString(), new Date()));

            // 公式二计算
            BigDecimal result2 = result1.add(BigDecimal.valueOf(variable2).divide(BigDecimal.valueOf(variable1), 2, RoundingMode.HALF_UP));
            resultMapper.insertResult(new Result(calcName, "公式二", result2.floatValue(), content.toString(), new Date()));

            // 公式三计算
            if (current[selectedIndex] > 0) {  // 确保选择的第一个氨基酸的数量不为0
                BigDecimal totalForFormula3 = BigDecimal.ZERO;
                for (int i = 0; i < current.length; i++) {
                    if (i == selectedIndex) {
                        totalForFormula3 = totalForFormula3.add(BigDecimal.valueOf(values[i] * (int) (Math.random() * (maxCounts[i] - 1) + 1))); // 1 到 maxCounts[i] 随机值
                    } else {
                        totalForFormula3 = totalForFormula3.add(BigDecimal.valueOf(values[i] * current[i]));
                    }
                }
                BigDecimal result3 = totalForFormula3.add(BigDecimal.valueOf(1.0073f * variable1)).divide(BigDecimal.valueOf(variable1), 2, RoundingMode.HALF_UP).add(BigDecimal.valueOf(variable3).divide(BigDecimal.valueOf(variable1), 2, RoundingMode.HALF_UP));
                resultMapper.insertResult(new Result(calcName, "公式三", result3.floatValue(), content.toString(), new Date()));
            }

            progress.incrementAndGet();
            return;
        }

        for (int i = 0; i <= maxCounts[index]; i++) {
            current[index] = i;
            if (index == selectedIndex && i == 0) continue;  // 跳过选择的第一个氨基酸数量为0的情况
            generateCombinations(current, maxCounts, values, names, index + 1, calcName, variable1, variable2, variable3, selectedIndex);
        }
    }

    public int getProgress() {
        return progress.get();
    }

    public int getTotalCombinations() {
        return totalCombinations;
    }
}
